'''
1、基本概念：
  ① web框架和web服务器的关系：
       web服务器主要是接收用户的http请求，根据用户的请求返回不同的资源数据
       静态web服务器返回的是静态资源数据
       web框架专门负责处理用户的动态资源请求，为web服务器提供服务的应用程序
  ② 静态资源：不需要经常变化的资源，这种资源web服务器可以提前准备好，如png、jpg、css、js文件
  ③ 动态资源：经常变化的资源，如html文件
  ④ WSGI协议：web服务器和web框架之间进行协同工作的一个规则
  ⑤ web框架：
       创建web框架程序
       接收web服务器的动态资源请求
       处理web服务器的动态资源请求，并把处理结果返回给web服务器
       web服务器把处理结果组装成响应报文（http协议格式）发送给浏览器
2、日志等级（低->高）
       debug：调试bug时使用
       info：正常允许时使用
       warning：未按预期运行时使用，并不是错误，如用户登录密码错误
       error：程序出错误时使用，如IO操作失败
       critical：特别严重的错误，程序不能继续运行时使用，如磁盘空间为空，一般很少用
          一般放在程序入口
'''
import socket
import threading
import frame06
import logging
import sys

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    filename="log.txt",
                    filemode="w")
#  把提供服务的web服务器抽象成一个类
class HttpWebServer:
    # 提供web服务器的初始化方法（int-创建socket对象、handle、start）
    def __int__(self):
        # 编写一个TCP服务端程序
        # 创建socket
        self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置端口复用
        self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定地址
        self.tcp_socket.bind(("", 9090))
        # 设置监听
        self.tcp_socket.listen(128)

    def handle(self, conn):
        # 获取浏览器的请求信息
        recv_data = conn.recv(1024).decode()
        print(recv_data)
        # 获取用户请求资源的路径
        req_data = recv_data.split(" ")
        print(req_data)

        # 判断客户端是否关闭
        if len(req_data) == 1:
            conn.close()
            return
        # 请求资源的路径
        req_path = req_data[1]
        if req_path == "/":
            req_path = "/index.html"
        # 服务器判断是否是动态资源
        if req_path.endswith(".html"):
            """动态资源"""

            logging.info("动态资源" + req_path)

            # 应答行
            response_line = "/HTTP1.1 200 ok\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # if req_path == "/index.html":
            #     # 应答体
            #     response_body = frame.index()
            # elif req_path == "/center.html":
            #     response_body = frame.center()
            # else:
            #     response_body = frame.error()
            response_body = frame06.application(req_path)

            # 应答数据
            # 组装指定文件数据的响应报文，发送给浏览器
            response_data = response_line + response_header + "\r\n" + response_body
            conn.send(response_data.encode())
            conn.close()
        else:
            """静态资源"""

            logging.info("静态资源" + req_path)

            # 333、读取固定页面数据，把页面数据组装成http响应报文数据发送给浏览器
            # 根据请求资源的路径，读取指定文件的数据
            try:
                with open("./static" + req_path, "rb") as f:
                    f_data = f.read()
            except Exception as e:

                logging.error("访问错误路径" + str(e))

                # 应答行
                response_line = "/HTTP1.1 200 ok\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = f_data
                # 应答数据
                # 组装指定文件数据的响应报文，发送给浏览器
                response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body
                conn.send(response_data)
            else:
                # 返回404错误数据
                response_line = "/HTTP1.1 404 Not Fund\r\n"
                response_header = "Server:pwb\r\n"
                response_body = "404 Not Fund sorry"
                response_data = (response_line + response_header + "\r\n" + response_body).encode('utf-8')
                conn.send(response_data)
            finally:
                # http响应报文数据发送完成以后，关闭服务于客户端的套接字
                conn.close()

    # 开启web服务器方法，让web服务器处理客户端请求操作
    def start(self):
        while True:
            # 222、获取浏览器发送的http请求报文数据
            # 建立链接
            conn, ip = self.tcp_socket.accept()
            # 创建子线程
            sub_thread = threading.Thread(target=self.handle, args=(conn, ))
            sub_thread.start()

if __name__ == '__main__':
    # 创建服务器对象
    my_web_server = HttpWebServer()
    # 启动服务器
    my_web_server.start()